package com.bgi.cg.oss4j.provider.aliyun.service;

import cn.hutool.core.date.DateUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectResult;
import com.bgi.cg.api.AbstractOssService;
import com.bgi.cg.api.entity.OssResponse;
import com.bgi.cg.oss4j.common.factory.BeanFactory;
import com.bgi.cg.oss4j.common.util.OssUtil;
import com.bgi.cg.oss4j.provider._base.OssSupplierType;
import com.bgi.cg.oss4j.provider.aliyun.config.AliyunOssConfig;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.function.Function;

/**
 * @Description 阿里云
 * @Author Z.cg
 * @Date 2023/9/8
 * @Version 1.0
 **/
@Slf4j
public class AliyunOssService extends AbstractOssService {
    private final AliyunOssConfig config;
    private static OSSClient client;

    public AliyunOssService(AliyunOssConfig aliyunOssConfig, Executor pool) {
        super(pool);
        this.config = aliyunOssConfig;
        client = new OSSClient(aliyunOssConfig.getEndPoint(), aliyunOssConfig.getAccessKey(), aliyunOssConfig.getAccessKeySecret());
        if (aliyunOssConfig.isBucketAutoCreate()) {
            try {
                if (!client.doesBucketExist(aliyunOssConfig.getBucket())) {
                    client.createBucket(aliyunOssConfig.getBucket());
                }
            } catch (Exception exception) {
                log.error("【{}】OSS创建桶失败：{}", OssSupplierType.ALI.name(), exception.getMessage());
            }

        }
    }

    @Override
    public OssResponse upload(File file) {
        return upload(file, config.getBucket());
    }

    @Override
    public OssResponse upload(File file, String bucketName) {
        return upload(file, bucketName, OssUtil::generatePath);
    }

    @Override
    public OssResponse upload(File file, Function<File, String> fileKeyFunction) {
        return upload(file, config.getBucket(), fileKeyFunction);
    }

    @Override
    public OssResponse upload(File file, String bucketName, Function<File, String> fileKeyFunction) {
        valiConfigIsOk();
        // 生成存储的文件名即存储的路径
        String fileName = fileKeyFunction.apply(file);
        OssResponse ossResponse = OssResponse.builder().code("0").filePath(fileName).ossType(OssSupplierType.ALI.name()).build();
        ossResponse.setOssType(OssSupplierType.ALI.toString());
        try (InputStream fis = new FileInputStream(file)) {
            PutObjectResult putObjectResult = client.putObject(bucketName, fileName, fis);
            return ossResponse;
        } catch (IOException exception) {
            log.error("【{}】OSS文件上传失败：{}", OssSupplierType.ALI.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
            return ossResponse;
        }
    }

    @Override
    public OssResponse genPreviewUrl(String fileName) {
        return genPreviewUrl(fileName, config.getBucket());
    }

    @Override
    public OssResponse genPreviewUrl(String fileName, String bucketName) {
        // 根据配置参数生成过期时间（预览地址的过期时间）
        Integer expireMs = BeanFactory.getOssConfig().getDownloadUrlExpireMs();
        Date expireTime = DateUtil.offsetSecond(new Date(), expireMs);
        // 获取预览地址
        URL url = client.generatePresignedUrl(bucketName, fileName, expireTime);
        OssResponse ossResponse = OssResponse.builder().code("0").previewUrl(url.toString()).build();
        return ossResponse;
    }

    @Override
    public OssResponse delete(String fileName) {
        return delete(fileName, config.getBucket());
    }

    @Override
    public OssResponse delete(String fileName, String bucketName) {
        OssResponse ossResponse = OssResponse.builder().code("0").build();
        try {
            client.deleteObject(bucketName, fileName);
        } catch (Exception exception) {
            log.error("【{}】OSS文件删除失败：{}", OssSupplierType.ALI.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
        }
        return ossResponse;
    }

    void valiConfigIsOk() {
        if (!config.configIsOk()) {
            throw new RuntimeException("未配置[accessKey,accessKeySecret,bucket,endPoint,region]值");
        }
    }
}
